#include "stdafx.h"

#include <string>
#include <iostream>
#include <sstream>
#include <vector>

#include "basePlayer.h"
#include "baseBoard.h"
#include "baseDeck.h"
#include "baseCard.h"
#include "baseToken.h"
#include "Game.h"

class basePlayer;
class baseDeck;
class baseBoard;
class baseToken;
class baseCard;

using namespace std;

Game::Game(baseBoard* aBoard, baseDeck* aDeck, baseDeck* aTrash, int aTokenNum) : board(aBoard), deck(aDeck), trash(aTrash), tokenNumber(aTokenNum)
{
    players.clear();
    activePlayerIndex = -1;
}

Game::~Game()
{
    int numPlayers = countPlayers();

    for(int i=0; i<numPlayers; i++)
    {
        delete players[i];
        players[i] = NULL;
    }
}

vector<basePlayer*> Game::getPlayers()
{
    return players;
}

baseBoard* Game::getBoard()
{
    return board;
}

baseDeck* Game::getDeck()
{
    return deck;
}

baseDeck* Game::getTrash()
{
    return trash;
}

int Game::getMaxPlayers()
{
    return maxPlayers;
}

int Game::getTokenNumber()
{
    return tokenNumber;
}

void Game::setTokenNumber(int aTokenNum)
{
    tokenNumber = aTokenNum;
}

string Game::toString()
{
    stringstream out;

    out << "Players: " << countPlayers() << endl << endl;

    out << playerListToString();

    return out.str();
}

void Game::toString(ostream &out)
{
    out << toString();
}

void Game::toString(string &str)
{
    str = str + toString();
}

int Game::countPlayers()
{
    return players.size();
}

void Game::addPlayer(basePlayer& aPlayer)
{
    players.push_back(&aPlayer);
    
    if(activePlayerIndex == -1)
        activePlayerIndex = 0;
}

string Game::playerListToString()
{
    stringstream out;

    for(int i = 0; i<countPlayers(); i++)
    {
        if(players[i])
            out << players[i]->toString();
    }

    return out.str();
}

void Game::display()
{
    board->display();
    if(activePlayerIndex != -1)
        getActivePlayer()->display();
}

basePlayer* Game::getActivePlayer()
{
    if(players[activePlayerIndex]->getActionsLeft() <= 0)
    {
        players[activePlayerIndex]->giveAllActions();
        activePlayerIndex++;

        if(activePlayerIndex >= countPlayers())
            activePlayerIndex = 0;
    }

    return players[activePlayerIndex];
}

void Game::checkForWonCards()
{
    vector<vector<baseCard*>> cards;
    vector<basePlayer*>::iterator vit_end(players.begin()+activePlayerIndex), vend_end(players.end());
    vector<basePlayer*>::iterator vit_start(players.begin()), vend_start(players.begin()+activePlayerIndex);

    for(;vit_end!=vend_end;++vit_end)
    {
        cards = board->getCardsMatrix();

        for(int j=0; j<board->getHeight(); j++)
        {
            for(int k=0; k<board->getWidth(); k++)
            {
                if(cards[j][k]
				   && cards[j][k]->isPayed(players[activePlayerIndex]->getColor()))
                {
                    (*vit_end)->winCard(*cards[j][k]);
                }
            }
        }
    }

    for(;vit_start!=vend_start;++vit_start)
    {
        cards = board->getCardsMatrix();

        for(int j=0; j<board->getHeight(); j++)
        {
            for(int k=0; k<board->getWidth(); k++)
            {
                if(cards[j][k]
				   && cards[j][k]->isPayed(players[activePlayerIndex]->getColor()))
                {
                    (*vit_start)->winCard(*cards[j][k]);
                }
            }
        }
    }
}
